package hirt;

import java.awt.Point;
//import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
//import java.io.InputStreamReader;
import java.io.OutputStream;
//import java.io.PrintWriter;
//import java.net.DatagramPacket;
//import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Server Child is an extention of ServerParent
 * It is meant to correspond to a single client
 * and therfore a single player
 * It reacts to all the clients messages with the apprortaie response
 * and updates ServerParents centeralized data
 * It can also communicate with any of the clients to keep them up to date
 * and does so whenever it updates the centralized data
 * @author zamille
 */
public class ServerChild extends ServerParent1 {
        /** Socket used to write message to the client*/
	Socket server;
        /** Whether or not the server is listening*/
	boolean listen = true;
        /** The player asscoiated with this child*/
        Player remotePlayer;
        /** This childs parent*/
        ServerParent1 parent;

	public ServerChild(Socket socket, ServerParent1 parent) throws SocketException, IOException {
		// TODO Auto-generated constructor stub
		super("ServerChild");
		server = socket;
                this.parent = parent;
                this.parent.outSockets.add(socket);
		System.out.println("Child set up");
                remotePlayer = new Player(this.parent.getNextName());
                try {
                    remotePlayer.joinSession(parent.gameSession);
                } catch (Exception ex) {
                    System.out.println("ERROR JOINGING SESSION:  " + ex.getMessage());
                }
	}

    @Override
	public void run()
	{
            try
            {
                    System.out.println("Child running");
                    InputStream in = server.getInputStream();
                    this.InializeClient();
                    CreationAction create = new CreationAction(remotePlayer, true);
                    //Message message = new Message(Message.LOCALPLAYERCREATE_MESSAGE, create);
                    //SendSingleMessage(message);
                    Message message = new Message(Message.CREATE_MESSAGE, create);
                    parent.SendMessage(message.toByte(), server);
                    parent.gameSession.addAction(create);
                    Vector<Item> list;
                    System.out.println("1");

                    while (listen)
                    {
                            System.out.println("2");
                            byte[] buffer = new byte[256];
                            in.read(buffer);
                            ByteBuffer bytes = ByteBuffer.wrap(buffer);
                            if (parent.gameSession.currentScenario != null)
                                list = parent.gameSession.currentScenario.itemList;
                            else
                                list = new Vector<Item>();
                            System.out.println("3");
                            Message inputLine = new Message(bytes, list);
                            System.out.println("4");


                            recieveMessage(inputLine);
                            ByteBuffer buf = ByteBuffer.wrap(buffer);
                            //SendMessage(buf);
                            //SendTime();
                    }
            } catch (Exception ex)
            {
                    System.out.println("run problem:  " + ex.getMessage());
            }
            try {
                    server.close();
            } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
            outSockets.remove(server);
            RemoveAction remove = new RemoveAction(remotePlayer);
            Message message = new Message(Message.REMOVE_MESSAGE, remove);
            try {
                parent.SendMessage(message);
            } catch (IOException ex) {
                System.out.println("ERROR sending player removal: " + ex.getMessage());
            }
            parent.gameSession.addAction(remove);
            parent.gameSession.playerList.remove(remotePlayer);
            //if (parent.gameSession.currentScenario != null)
                //parent.gameSession.currentScenario.removeItem(remotePlayer);
            parent.children.remove(this);
            if (parent.children.size()==0)
            {
                parent.countTime=false;
                parent.resetPlayerCount();
                Scenario currentScenario = parent.gameSession.currentScenario;
                currentScenario.basicLoadFromFile(currentScenario.getOriginalFile());
                parent.gameSession.currentScenario = new Scenario();
                parent.gameSession.setMode(Session.DEFAULT_MODE);
                parent.gameSession.actionLog.clear();
                parent.arrivalQueue.clear();
                

            }
            System.out.println("Child is closing");

	}

    /**
     * Takes a message recieved from the client and calls the porper method to deal with it
     * based on the message type
     * @param inputLine
     * @throws IOException
     */
	private void recieveMessage(Message inputLine) throws IOException
        {
            System.out.println("Recieved message of type: " + inputLine.type);
            if (inputLine.content != null)
                inputLine.content.setStartTime(parent.gameSession.currentScenario.getCurrentTime());
            try
            {
                switch (inputLine.type)
                {
                    case 0: 				//close connection message
                            //GUI.writeChatMessage("Connection closed\n");
                            break;
                    case Message.CHAT_MESSAGE: 				//chat message
                        parent.gameSession.chatLog.add((CommunicationAction)inputLine.content);
                        parent.gameSession.addAction(inputLine.content);
                        parent.SendMessage(inputLine);
                        break;
                    case Message.MOVE_MESSAGE:
                        if (handleMoves((MovementAction)inputLine.content))
                        {
                            parent.gameSession.addAction(inputLine.content);
                            parent.SendMessage(inputLine);
                        }
                        break;
                    case Message.REQUEST_CREATE_MESSAGE:
                        handleCreationRequest((RequestCreateAction)inputLine.content);
                        //parent.SendMessage(inputLine);
                        break;
                    case Message.TRANSFER_MESSAGE:
                        handleTransfer((TransferAction)inputLine.content);
                        parent.gameSession.addAction(inputLine.content);
                        parent.SendMessage(inputLine);
                        break;
                    case Message.PLAYERCHANGE_MESSAGE:
                        if (handlePlayerChange((PlayerChangeAction)inputLine.content))
                        {
                            //parent.gameSession.addAction(inputLine.content);
                            parent.SendMessage(inputLine);
                        }
                        break;
                    case Message.LOCALPLAYERCREATE_MESSAGE:
                        parent.SendMessage(inputLine);
                        break;
                    case Message.REMOVE_MESSAGE:
                        ByteBuffer bytes = inputLine.toByte();
                        receiveRemoveItem((RemoveAction) inputLine.content);
                        //parent.gameSession.addAction(inputLine.content);
                        //parent.SendMessage(bytes);
                        break;
                    case Message.REVIEW_MODE_MESSAGE:
                    case Message.PLAY_MODE_MESSAGE:
                    case Message.EDITOR_MODE_MESSAGE:
                        handleModeChange(inputLine.type);
                        parent.SendMessage(inputLine);
                        if (parent.gameSession.mode == Session.MODE_REVIEW)
                            SendReplay();
                        break;
                    case Message.LOAD_SCENARIO_MESSAGE:
                        loadCurrentScenario((ScenarioDataAction)inputLine.content);
                        break;
                    case Message.SAVE_SCENARIO_MESSAGE:
                        if (saveCurrentScenario((ScenarioDataAction)inputLine.content))
                        {
                            //inputLine.type = Message.SCENARIO_DATA_MESSAGE;
                            parent.SendMessage(inputLine);
                        }
                        break;
                    case Message.CAR_CONDITION_MESSAGE:
                        handleCarConditionChange((CarConditionAction) inputLine.content);
                        parent.gameSession.addAction(inputLine.content);
                        parent.SendMessage(inputLine);
                        break;
                    case Message.SET_LANE_ADJACENCY_MESSAGE:
                        setLaneAdjacencies((TransferAction) inputLine.content);
                        break;
                    default: System.out.println("Unrecognized type: " + inputLine.type);
                        parent.SendMessage(inputLine);
                }
            }
            catch (Exception ex)
            {
                System.out.println("ERROR in recieve message: " + ex.getMessage());
            }
            
                  /*          listen = false;
                            System.out.println("Child done listening");


                    else if(inputLine.type == 1)
                    {
                            SendMessage(inputLine);
                    }*/
        }

	/**
         * Sends a message out to this childs client and no one else
         * @param message
         */
        private void SendSingleMessage(Message message)
        {
            OutputStream out = null;
            ByteBuffer buf = message.toByte();
           try
           {
                out = server.getOutputStream();
                out.write(buf.array());
           }
           catch (Exception ex)
           {
               System.out.println("ERROR sending message:  " + ex.getMessage());
           }


            System.out.println("Child sent message");
        }

        /**
         * Initializes the client with all the information it needs to first join
         * into this session
         * @throws IOException
         * @throws Exception
         */
        private void InializeClient() throws IOException, Exception
        {
            //int lanes = parent.gameSession.currentScenario.getNumberOfLanes();
            //System.out.println("NumOfLanes = " + lanes);
           // CreationAction create = new CreationAction(lanes);
            //Message message = new Message(Message.CREATE_MESSAGE,create);
            //SendSingleMessage(message);
            sendSessionMode();

            sendScenarioList();

            sendAllItems(false);

            System.out.println("Finished Looping");
            //remotePlayer.joinSession(parent.gameSession);
            System.out.println("Joined");


        }

        /**
         * Sends out information on every item in the master item list
         * if All is set to true it send the info to everyone
         * otherwise it only sends it to the client
         * @param All
         */
        private void sendAllItems(boolean All)
        {
            //OutputStream out = null;
            try {
                System.out.println("Initializing");
                //out = server.getOutputStream();
                System.out.println("Got Output");
                Vector<Item> items = parent.gameSession.currentScenario.getItemList();
                Message message;
                CreationAction create;
                //ByteBuffer tmp;
                System.out.println("About to Loop");
                for (int i = 0; i < items.size(); i++) {
                    System.out.println(items.get(i).id);
                    /*if (items.get(i) instanceof Item2D)
                    {
                        Item2D item = (Item2D)items.get(i);
                        System.out.println("Point:  " + item.getPosition().x + ", " + item.getPosition().y);
                    }*/
                    create = new CreationAction(items.get(i));
                    Item item = items.get(i);
                    System.out.print(item.type + "\tItem: " + item.getId());
                    if (item.owner != null) {
                        System.out.println("\tis owned by" + item.container.getId());
                    } else {
                        System.out.println();
                    }
                    if (i == remotePlayer.getId() && !All) {
                        message = new Message(Message.LOCALPLAYERCREATE_MESSAGE, create);
                    } else {
                        message = new Message(Message.CREATE_MESSAGE, create);
                    }

                    if (All)
                        SendMessage(message);
                    else
                        SendSingleMessage(message);
                    //tmp = message.toByte();
                    //out.write(tmp.array());
                }
            } catch (IOException ex) {
                Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);

            }
            if (All)
                parent.assignPlayers();

        }

        /**
         * Tells the client to clear all scenario information
         * @param All
         */
        private void ClearClient(boolean All)
        {
            /*Vector<Item> list = parent.gameSession.currentScenario.getItemList();
            Message message;
            RemoveAction action;
            try
            {
                for (int i = list.size()-1; i >=0; i--)
                {
                    action = new RemoveAction(list.get(i));
                    message = new Message(Message.REMOVE_MESSAGE, action);
                    SendMessage(message);
                }
            }
            catch (Exception ex)
            {
                System.out.println("Problem clearing client:  " + ex.getMessage());
            }*/
            Message message = new Message(Message.CLEAR_SCENARIO_MESSAGE);
            try {
                if (All)
                    SendMessage(message);
                else
                    SendSingleMessage(message);
            } catch (IOException ex) {
                Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        /**
         * Called when the server receives a Move Message
         * it calculates if there is a collision and if not it
         * moves the item to the new location
         * @param movement
         * @return valid move
         */
        public boolean handleMoves(MovementAction movement)
        {
            //System.out.println("HandlesMoves");
            Scenario scenario = parent.gameSession.currentScenario;
            Vector<Item> items = scenario.getItemList();
            Item2D actor = (Item2D)items.get(movement.actor.getId());
            Point origin = actor.getPosition();
            float originalAngle = actor.getAngle();

            actor.setPosition(movement.endPoint);
            actor.setAngle(movement.getAngle());

            if (scenario.detectCollision(actor))
            {
                actor.setAngle(originalAngle);
                actor.setPosition(origin);
                return false;
            }
            return true;
            //parent.gameSession.currentScenario.set
            //items.set(movement.actor.getId(), actor);
           // parent.gameSession.currentScenario.addItem(actor, movement.actor.getId());
            //parent.gameSession.currentScenario.set

        }

    /**
     * Called when the server receives a Player Change Message
     * Detrermines if the change is valid and if so
     * it changes the player and tells everyone else to update their player
     * in the same way
     * @param action
     * @return
     */
    private boolean handlePlayerChange(PlayerChangeAction action) {
        System.out.println("HandlesPlayerChange");
        Vector<Item> items = parent.gameSession.currentScenario.getItemList();
        Item item;
        Player tmpPlayer;
        boolean taken = false;
        Player player = (Player)items.get(action.actor.getId());
        switch (action.type)
        {
            case PlayerChangeAction.CHANGE_NAME:
                String newName = action.newName;
                if (!newName.equals(""))
                {
                    for (int i = 0; i < items.size(); i++)
                    {
                        item = items.get(i);
                        if (item instanceof Player)
                        {
                            tmpPlayer = (Player)item;
                            if (tmpPlayer.getName().equals(newName))
                            {
                                taken = true;
                                break;
                            }
                        }
                    }
                    if (!taken)
                    {
                        player.setName(action.newName);

                    }
                    return !taken;
                }
                else
                    return false;
                
            case PlayerChangeAction.ADD_ROLE:
                try {
                    int roleID = action.newRole.getId();
                    Vector<Role> roleList;
                    for (int i = 0; i < items.size(); i++)
                    {
                        item = items.get(i);
                        if (item instanceof Player)
                        {
                            tmpPlayer = (Player)item;
                            roleList = tmpPlayer.getRoles();
                            for (int j = 0; j < roleList.size();j++)
                            {
                                if (roleList.get(j).getId() == roleID)
                                {
                                    taken = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (!taken)
                    {
                        player.addRole(roleID);

                    }
                    return !taken;
                } catch (Exception ex) {
                    return false;
                }
               //return true;
            case PlayerChangeAction.REMOVE_ROLE:
                try {
                    player.removeRole(action.newRole.getId());

                } catch (Exception ex) {
                    return false;
                }
                return true;
        }
        return false;
    }

    /**
     * Called when the server receives a Transfer Message
     * Moves the item to it's new inventory location
     * @param transferAction
     */
    private void handleTransfer(TransferAction transferAction) {
        Item movedItem = transferAction.moved;
        Item tempItem = transferAction.reciever;
        tempItem.putItem( movedItem );
    }

    /**
     * clears the clients
     * reloads the current scenario from its save file
     * sends out every action in the actionlog to replay the scenario
     */
    private void SendReplay() {
        ClearClient(true);
        Scenario scene = parent.gameSession.currentScenario;
        String file = scene.getOriginalFile();
        Scenario newScene = new Scenario();
        newScene.loadFromFile(file);  //reload the scenario to start from a blank slate

        setCurrentScenario(newScene);
        try {
            parent.gameSession.currentScenario.setCurrentTime(0.0);
        } catch (Exception ex) {
            Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);
        }
        parent.countTime = true;
        //parent.timeCounter.start();

        Vector<Action> log = parent.gameSession.actionLog;
        Message message;
        Action action;
        double time;
        System.out.println("Log Size: " + log.size());
        for (int i = 0; i < log.size(); i++)
        {
            action = log.get(i);
            time = parent.gameSession.currentScenario.getCurrentTime();
            if (action.startTime <= time)
            {
                message = new Message(log.get(i));
                try {
                    parent.SendMessage(message);
                } catch (IOException ex) {
                    System.out.println("Couldn't send message # " + i + ":   " + ex.getMessage());
                }
            }
            else
            {
                i--;
                 try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    System.out.println("Interupted sleep:   " + ex.getMessage());
                }
            }
            
        }
        //parent.timeCounter.stop();
    }

    /**
     * Called when the server receives a CreationRequest message
     * creates an item(or multiple) of the spcified paremeters
     * adds it to the master item list and tells all the players about it
     * @param creationAction
     */
    private void handleCreationRequest(RequestCreateAction creationAction) {
        String Class = creationAction.Class;
        String type = creationAction.type;
        Point position = creationAction.position;
        int ID = creationAction.ownerID;
        int amount = creationAction.amount;
        
        Item owner = null;
        if (ID >= 0)
        owner = parent.gameSession.currentScenario.getItemById(ID);
        for (int i = 0; i < amount; i++)
        {
                
            Item createdItem;
            if (Class.equals(" hirt.Item"))
            {
                createdItem = new Item(type, owner);
            }
            else if (Class.equals(" hirt.Item2D"))
            {
                Item2D item = new Item2D(type, owner, position.x,position.y);
                int index = ServerConstants.getItemIndexByType(type);
                if (index >= 0)
                {
                    Point dimensions = ServerConstants.ITEM2D_DIMENSIONS[index];
                    item.setWidth(dimensions.x);
                    item.setHeight(dimensions.y);

                }
                createdItem = item;
                owner.putItem(createdItem);
            }
            else if (Class.equals(" hirt.Automobile"))
            {
                int role = -1;
                for (int j = 0; j < Role.NUMBER_OF_ROLES; j++)
                {
                    if (ServerConstants.ITEM_TYPE_NAME[j].equals(type))
                    {
                        role = j;    //gets the role of the car being created
                        break;
                    }
                }

                /*if (role >= 0)
                {
                    Automobile car = new Automobile(role);
                    car.setPosition(position.x, position.y);
                    createdItem = car;
                    createdItem.setOwner(owner);
                }
                else
                    createdItem = null;*/
                createdItem = parent.gameSession.currentScenario.initializeCar(role,position.x, position.y, 0);
            }
            else if (Class.equals(" hirt.Lane"))
            {
                createdItem = new Lane(type, position.x, position.y );
                createdItem.setOwner(owner);
            }
            else
                createdItem = null;

            if (createdItem != null)
            {
                if(!(createdItem instanceof Automobile))
                {
                    createdItem.setContainer(owner);
                    parent.gameSession.currentScenario.addItem(createdItem);
                }

                CreationAction create = new CreationAction(createdItem);
                create.startTime = parent.gameSession.getCurrentScenario().getCurrentTime();
                create.firstTime = true;
                Message message = new Message(Message.CREATE_MESSAGE, create);
                if (!(parent.gameSession.mode == Session.MODE_EDITOR))
                {
                    if (createdItem.owner != null)
                        createdItem.owner.removeItem(createdItem);
                    if (createdItem.container != null)
                        createdItem.container.removeItem(createdItem);
                    parent.arrivalQueue.add(create);

                }

            
                try {
                    SendMessage(message);
                } catch (IOException ex) {
                    Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);
                }

                parent.gameSession.addAction(create);
                if (createdItem instanceof Automobile)
                {
                    //parent.addCones((Automobile) createdItem);
                    parent.addDefaultItems( ( Automobile )createdItem );
                }
            }
            
        }




    }

    
    /**
     * Changes mode to the passed type
     * @param new Mode, Possible Values are the static mode  variables in Session
     */
    private void handleModeChange(byte type) {
        int newMode = 0;
        Session session = parent.gameSession;
        if (type == Message.REVIEW_MODE_MESSAGE)
        {
            newMode = Session.MODE_REVIEW;
            parent.countTime = true;
            //SendReplay();
        }
        else if (type == Message.EDITOR_MODE_MESSAGE)
        {
            newMode = Session.MODE_EDITOR;
            Player player;
            PlayerChangeAction action;
            Message message;
            try
            {
                for (int i = 0; i < Role.NUMBER_OF_ROLES; i++)
                {
                    if (!remotePlayer.containsRole(i))
                    {
                        player = session.getPlayerByRole(i);
                        if (player != null)
                            player.removeRole(i);
                        action = new PlayerChangeAction( remotePlayer, i);
                        remotePlayer.addRole(i);
                        message = new Message(Message.PLAYERCHANGE_MESSAGE,action);
                        SendMessage(message);
                    }
                }
            }
            catch (Exception ex)
            {
                System.out.println("ERROR adding many roles:  " + ex.getMessage());
            }
            parent.countTime = false;
        }
        else if (type == Message.PLAY_MODE_MESSAGE)
        {
            newMode = Session.MODE_PLAY;
            Player player;
            PlayerChangeAction action;
            Message message;
            try
            {
                for (int i = 0; i < Role.NUMBER_OF_ROLES; i++)
                {

                    player = session.getPlayerByRole(i);
                    if (player != null)
                    {
                        action = new PlayerChangeAction( player, i);
                        player.removeRole(i);
                        
                        message = new Message(Message.PLAYERCHANGE_MESSAGE,action);
                        SendMessage(message);
                    }

                }
            }
            catch (Exception ex)
            {
                System.out.println("ERROR removing many roles:  " + ex.getMessage());
            }
            parent.countTime = true;
        }
        parent.gameSession.setMode(newMode);
        System.out.println("MODE CHANGE: " + type);

    }

    /**
     * sends the name of every scenario to the client
     * so it can formulate it's own scenario list for
     * the player to choose from
     */
    private void sendScenarioList() {
        Vector<Scenario> list = parent.gameSession.getScenarioList();
        ScenarioDataAction data;
        for (int i = 0; i < list.size(); i++)
        {
            data = new ScenarioDataAction(list.get(i).getName(), list.get(i).getDescription());
            Message message = new Message(Message.SCENARIO_DATA_MESSAGE,data);
            SendSingleMessage(message);

        }
    }

    /**
     * Called when the server receives a load scenario message
     * this loads the sceanrio from the file with a passed name
     * and makes it the current scenario
     * @param scenarioDataAction
     */
    private void loadCurrentScenario(ScenarioDataAction scenarioDataAction) {
        //System.out.println("LOAD SCENARIO");
        String name = scenarioDataAction.getName();
        Scenario scenario = null;
        boolean found = false;
        Vector <Scenario> list = parent.gameSession.scenarioList;
        for (int i = 0; i < list.size(); i++)
        {
            if (list.get(i).name.equals(name))
            {
                scenario = list.get(i);
                found = true;
                break;
            }
        }
        if (found)
        {
            scenario.itemList.clear();
            scenario.world.itemList.clear();
            scenario.loadFromFile(scenario.getOriginalFile());
            setCurrentScenario(scenario);
            scenario.currentTime = 0.0;
            parent.countTime = true;
            parent.gameSession.actionLog.clear();

        }
    }

    /**
     * Sets the passed scenario to the current scenario
     * @param scenario
     */
    private void setCurrentScenario(Scenario scenario)
    {
        ClearClient(true);
         try {
            parent.gameSession.setCurrentScenario(scenario);
            Vector<Player> playerList = parent.gameSession.getPlayerList();
            for (int i = 0; i < playerList.size(); i++)
                parent.gameSession.currentScenario.addItem(playerList.get(i));

            sendAllItems(true);
        } catch (Exception ex) {
            System.out.println("ERROR setting new scenario:  " + ex.getMessage());
        }

    }

    /**
     * tells the client which item represents his local palyer
     */
    public void sendPlayerAssignment()
    {
        Action action = new Action(remotePlayer);
        Message message = new Message(Message.LOCALPLAYERASSIGN_MESSAGE, action);
        SendSingleMessage(message);
    }

    /**
     * Tells the client what mode the session is currently in
     */
    private void sendSessionMode() {
        Session gamesession = parent.gameSession;
        Message message = new Message();
        switch (gamesession.mode)
        {
                case Session.MODE_REVIEW: message= new Message(Message.REVIEW_MODE_MESSAGE); break;
                case Session.MODE_EDITOR: message= new Message(Message.EDITOR_MODE_MESSAGE); break;
                case Session.MODE_PLAY: message= new Message(Message.PLAY_MODE_MESSAGE); break;
        }
        SendSingleMessage(message);
    }

    /**
     * Saves the current scenario under the name passed in the scenarioDataAction
     * returns true if the write was successful
     * @param scenarioDataAction
     * @return
     */
    private boolean saveCurrentScenario(ScenarioDataAction scenarioDataAction) {
        String name = scenarioDataAction.getName();
        String desc = scenarioDataAction.getDescription();
        Scenario currentScenario = parent.gameSession.currentScenario;
        boolean result = false;
        if (currentScenario!=null)
        {
            currentScenario.setName(name);
            currentScenario.setDescription(desc);
            currentScenario.setAuthorName(remotePlayer.getName());
            String fileName = ServerConstants.SCENAIORFOLDERNAME + "/" + name + ".txt";
            result = currentScenario.writeToFile(fileName);

            parent.gameSession.scenarioList.clear();
            parent.gameSession.loadScenarioList(ServerConstants.SCENAIORFOLDERNAME);
        }
        return result;

    }

    /**
     * Called when the server receives a Remove Message
     * Decides whether to remove one item or multiple items
     * @param action
     */
    private void receiveRemoveItem(RemoveAction action) {
        //Item actor = removeAction.getActor();
        if (action.amount == 0)
            removeSingleItem(action.actor);
        else
            removeMultipleItems(action.actor,action.type,action.amount);

    }

    /**
     * Removes amount items of passed type from owner's inventory
     * @param owner
     * @param type
     * @param amount
     */
    private void removeMultipleItems(Item owner, String type, int amount)
    {
        Vector<Item> items = owner.getListOfItemsByType(type);
        Item item;
        RemoveAction remove;
        Message message;
        if (items != null)
        {
            for (int i = 0; i < items.size(); i++)
            {
                if (amount <= 0 )
                    break;
                else
                {
                    item = items.get(i);
                    owner.removeItem(item);
                    remove = new RemoveAction(item);
                    message = new Message(Message.REMOVE_MESSAGE, remove);
                    try {
                        SendMessage(message);
                    } catch (IOException ex) {
                        Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    amount--;
                }
            }
        }
        else
            System.out.println("No items to be removed????????????");
    }

    /**
     * Removes actor from the scene
     * althrough he remains i nthe item list
     * @param actor
     */
    private void removeSingleItem(Item actor)
    {
        if (actor instanceof Player)
        {
            Player plays = (Player)actor;
            try {
                parent.gameSession.removePlayer(plays);
            } catch (Exception ex) {
                System.out.println("removeItemMessage: Can't remove player from session: " + ex.getMessage());
            }

        }
        else
        {
            parent.gameSession.removeItem(actor);

        }

        RemoveAction remove = new RemoveAction(actor);
        Message message= new Message(Message.REMOVE_MESSAGE, remove);
        try {
            SendMessage(message);
        } catch (IOException ex) {
            Logger.getLogger(ServerChild.class.getName()).log(Level.SEVERE, null, ex);
        }
        parent.gameSession.addAction(remove);
    }

    /**
     * Called when the server receives a CarConditionAction
     * it sets the specified car to the specified conditions
     * @param action
     */
    private void handleCarConditionChange(CarConditionAction action) {
        Automobile car = (Automobile) action.actor;
        car.setFire(action.onFire);
        car.setDamage(action.damaged);
        car.setMoveable(action.movable);
        car.setLightStatus(action.lightSetting);
    }

    /**
     * Called when the server recieves a lane adjancency message
     * sets the lanes to the left and right of each other
     * @param action
     */
    private void setLaneAdjacencies(TransferAction action) {
        Lane left = (Lane) action.reciever;
        Lane right = (Lane) action.moved;
        left.setRight(right);
        right.setLeft(left);
    }

}
